home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
raytrace
/
rayshade
/
graphtal.lzh
/
Graphtal.Amiga
/
table.h
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-28
|
7KB
|
263 lines
/*
* Copyright (c) 1987, 1988, 1989, 1990, 1991 Stanford University
* Copyright (c) 1991 Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that (i) the above copyright notices and this permission notice appear in
* all copies of the software and related documentation, and (ii) the names of
* Stanford and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Stanford and Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*
* 12.8.92 Christoph Streit: remove_all function added
* modified for own purposes
*
* Generic object association table.
*/
#ifndef Table_H
#define Table_H
#include "Hash.h"
#include "rcString.h"
#if defined(__STDC__) || defined(__ANSI_CPP__) || defined(__DECCXX)
#define __TableEntry(Table) Table##_Entry
#define TableEntry(Table) __TableEntry(Table)
#define __TableIterator(Table) Table##_Iterator
#define TableIterator(Table) __TableIterator(Table)
#else
#define __TableEntry(Table) Table/**/_Entry
#define TableEntry(Table) __TableEntry(Table)
#define __TableIterator(Table) Table/**/_Iterator
#define TableIterator(Table) __TableIterator(Table)
#endif
#define declareTable(Table,Key,Value) \
class TableEntry(Table); \
\
class Table { \
public: \
Table(int); \
~Table(); \
\
int insert(const Key&, const Value&); \
int find(const Key&); \
int find_and_replace(const Key&, const Value&); \
int find_and_remove(const Key&, Value&); \
int lookup(const Key&, Value&); \
void remove(const Key&); \
void remove_all(); \
private: \
friend class TableIterator(Table); \
\
int size_; \
TableEntry(Table)** first_; \
TableEntry(Table)** last_; \
\
TableEntry(Table)*&probe(const Key&); \
}; \
\
class TableEntry(Table) { \
private: \
friend class Table; \
friend class TableIterator(Table); \
\
Key key_; \
Value value_; \
TableEntry(Table)* chain_; \
}; \
\
class TableIterator(Table) { \
public: \
TableIterator(Table)(const Table&); \
\
Key& cur_key(); \
Value& cur_value(); \
int more(); \
int next(); \
private: \
TableEntry(Table)* cur_; \
TableEntry(Table)** entry_; \
TableEntry(Table)** last_; \
}; \
\
inline Key& TableIterator(Table)::cur_key() { return cur_->key_; } \
inline Value& TableIterator(Table)::cur_value() { return cur_->value_; } \
inline int TableIterator(Table)::more() { return entry_ <= last_; }
/*
* Predefined hash functions
*/
inline unsigned long key_to_hash(long k) { return (unsigned long)k; }
//inline unsigned long key_to_hash(const void* k) { return (unsigned long)k; }
//inline unsigned long key_to_hash(const char* k)
//{ return (unsigned long)hash(k); }
inline unsigned long key_to_hash(const rcString& k)
{ return (unsigned long)hash((const char*) k); }
/*
* Table implementation
*/
#define implementTable(Table,Key,Value) \
Table::Table(int n) { \
for (size_ = 32; size_ < n; size_ <<= 1); \
first_ = new TableEntry(Table)*[size_]; \
--size_; \
last_ = &first_[size_]; \
for (register TableEntry(Table)** e = first_; e <= last_; e++) { \
*e = NULL; \
} \
} \
\
Table::~Table() { \
delete first_; \
} \
\
inline TableEntry(Table)*& Table::probe(const Key &i) { \
return first_[key_to_hash(i) & size_]; \
} \
\
int Table::insert(const Key& k, const Value &v) { \
if (find(k)) return 0; \
\
register TableEntry(Table)* e = new TableEntry(Table); \
e->key_ = k; \
e->value_ = v; \
register TableEntry(Table)** a = &probe(k); \
e->chain_ = *a; \
*a = e; \
return 1;\
} \
\
int Table::lookup(const Key &k, Value &v) { \
for (register TableEntry(Table)* e = probe(k); e != NULL; e = e->chain_) { \
if (e->key_ == k) { \
v = e->value_; \
return 1; \
} \
} \
return 0; \
} \
\
int Table::find(const Key &k) { \
for (register TableEntry(Table)* e = probe(k); e != NULL; e = e->chain_) { \
if (e->key_ == k) { \
return 1; \
} \
} \
return 0; \
} \
\
int Table::find_and_replace(const Key& k, const Value& v) { \
for (register TableEntry(Table)* e = probe(k); e != NULL; e = e->chain_) { \
if (e->key_ == k) { \
e->value_ = v; \
return 1; \
} \
} \
return 0; \
} \
\
int Table::find_and_remove(const Key& k, Value& v) { \
TableEntry(Table)** a = &probe(k); \
register TableEntry(Table)* e = *a; \
if (e != NULL) { \
if (e->key_ == k) { \
v = e->value_; \
*a = e->chain_; \
delete e; \
return 1; \
} else { \
register TableEntry(Table)* prev; \
do { \
prev = e; \
e = e->chain_; \
} while (e != NULL && e->key_ != k); \
if (e != NULL) { \
v = e->value_; \
prev->chain_ = e->chain_; \
delete e; \
return 1; \
} \
} \
} \
return 0; \
} \
\
void Table::remove(const Key &k) { \
TableEntry(Table)** a = &probe(k); \
register TableEntry(Table)* e = *a; \
if (e != NULL) { \
if (e->key_ == k) { \
*a = e->chain_; \
delete e; \
} else { \
register TableEntry(Table)* prev; \
do { \
prev = e; \
e = e->chain_; \
} while (e != NULL && e->key_ != k); \
if (e != NULL) { \
prev->chain_ = e->chain_; \
delete e; \
} \
} \
} \
} \
\
void Table::remove_all() \
{ \
TableIterator(Table) ti(*this); \
while (ti.more()) \
{ \
remove(ti.cur_key()); \
ti.next(); \
} \
} \
\
TableIterator(Table)::TableIterator(Table)(const Table& t) { \
last_ = t.last_; \
for (entry_ = t.first_; entry_ <= last_; entry_++) { \
cur_ = *entry_; \
if (cur_ != NULL) { \
break; \
} \
} \
} \
\
int TableIterator(Table)::next() { \
cur_ = cur_->chain_; \
if (cur_ != NULL) { \
return 1; \
} \
for (++entry_; entry_ <= last_; entry_++) { \
cur_ = *entry_; \
if (cur_ != NULL) { \
return 1; \
} \
} \
return 0; \
}
#endif // Table_H